package com.convert.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.convert.Constants.ConvertResult;
import com.convert.domain.ConvertRequest;
import com.convert.domain.ConvertResponse;
import com.convert.domain.LogResult;
import com.convert.domain.Message;
import com.convert.domain.RequestContent;
import com.convert.domain.ReservationResponse;
import com.convert.domain.ResponseContent;
import com.convert.domain.available.SummaryRatesResponse;
import com.convert.util.ExtractUtil;
import com.fasterxml.jackson.databind.ObjectMapper;

@Service
public class ConvertService {

    @Autowired
    private ObjectMapper objectMapper = new ObjectMapper();
    
    public ConvertResponse convert(List<String> paramList) {
        ConvertResponse response = new ConvertResponse();
        
        List<String> sources = ExtractUtil.extractSource(paramList);

        List<LogResult> results = new ArrayList<LogResult>();
        
        int numberOfIncompleteRequestBody = 0;
        int numberOfIncompleteResponseBody = 0;
        
        for(String source : sources) {
        	LogResult logResult = new LogResult();
            try {
                logResult = objectMapper.readValue(source, LogResult.class);
                results.add(logResult);
            } catch (IOException e) {
                if(source.contains(ConvertResult.REQUEST_BODY)) {
                    numberOfIncompleteRequestBody++;
                }
                if(source.contains(ConvertResult.RESPONSE_BODY)) {
                    numberOfIncompleteResponseBody++;
                }
            }
        }

        Map<String, String> requestMap = new HashMap<String, String>();
        Map<String, String> responseMap = new HashMap<String, String>();
        Iterator<LogResult> iterator = results.iterator();
        int numberOfRequestBody = 0;
        int numberOfResponseBody = 0;
        String pre_url = null;
        while(iterator.hasNext()) {
            
        	LogResult next = iterator.next();
        	
        	if(next != null && next.getLogData() != null && next.getLogData().getMessage() != null) {
	        	
        		Message nextMessage = next.getLogData().getMessage();
        		
        		if(StringUtils.isNotBlank(nextMessage.getRequestUri())){//event=request_response_log
        			
        			if(nextMessage.getMessageText().contains("Request")) {//request_body
        				
        				if(!requestMap.keySet().contains(nextMessage.getRequestUri())) {
        					requestMap.put(nextMessage.getRequestUri(), nextMessage.getRequestBody());
        					numberOfRequestBody++;
        				} else {
        					requestMap.put(nextMessage.getRequestUri(), requestMap.get(nextMessage.getRequestUri()) + nextMessage.getRequestBody());
        				}
        			} else {//response_body
        				
        				if(!responseMap.keySet().contains(nextMessage.getRequestUri())) {
        					responseMap.put(nextMessage.getRequestUri(), nextMessage.getResponseBody());
        					numberOfResponseBody++;
        				} else {
        					responseMap.put(nextMessage.getRequestUri(), responseMap.get(nextMessage.getRequestUri()) + nextMessage.getResponseBody());
        				}
        			}
	        		pre_url = nextMessage.getRequestUri(); 
	        	} else if(StringUtils.isNotBlank(nextMessage.getUrl())){//event=third-part
	        		if(StringUtils.isBlank(nextMessage.getHttpStatus())){// request_body
	        			
	        			if(!requestMap.keySet().contains(nextMessage.getUrl())) {
        					requestMap.put(nextMessage.getUrl(), nextMessage.getRequestBody());
        					numberOfRequestBody++;
        				} else {
        					requestMap.put(nextMessage.getUrl(), requestMap.get(nextMessage.getUrl()) + nextMessage.getRequestBody());
        				}
	        		} else {//response_body
	        			
	        			if(!responseMap.keySet().contains(nextMessage.getUrl())) {
	        				responseMap.put(nextMessage.getUrl(), nextMessage.getResponseBody());
        					numberOfResponseBody++;
        				} else {
        					responseMap.put(nextMessage.getUrl(), responseMap.get(nextMessage.getUrl()) + nextMessage.getResponseBody());
        				}
	        		}
	        		pre_url = nextMessage.getUrl(); 
	        	}
            }
            
        }
        
        List<RequestContent> requestContents = new ArrayList<RequestContent>();
        for(Entry<String, String> entry : requestMap.entrySet()) {
        		RequestContent requestContent = new RequestContent();
        		requestContent.setUrl(entry.getKey());
        		requestContent.setRequestBody(entry.getValue());
        		requestContents.add(requestContent);
        }
        
        List<ResponseContent> responseContents = new ArrayList<ResponseContent>();
        ReservationResponse[] reservationResponseArray = new ReservationResponse[0];
        SummaryRatesResponse summaryRateResponse = null;
        for(Entry<String, String> entry : responseMap.entrySet()) {
        		ResponseContent responseContent = new ResponseContent();
        		responseContent.setUrl(entry.getKey());
        		responseContent.setResponseBody(entry.getValue());
        		responseContents.add(responseContent);
        		
        		if(entry.getKey().equalsIgnoreCase("/gss-api/v1/reservations")){
        			try {
						reservationResponseArray = objectMapper.readValue(entry.getValue(), ReservationResponse[].class);
					} catch (Exception e) {
						// TODO Auto-generated catch block
					}
        		}
        		
        		
        		if(entry.getKey().substring(0, entry.getKey().length()-5).equalsIgnoreCase("/gss-api/v1/properties/available/")) {
        		    try {
        		        summaryRateResponse = objectMapper.readValue(entry.getValue(), SummaryRatesResponse.class);
        		    } catch (Exception e) {
                        // TODO Auto-generated catch block
                    }
        		}
        }
        
        List<ReservationResponse> reservationResponses = Stream.of(reservationResponseArray).collect(Collectors.toList());
        
        response.setRequestContents(requestContents);
        response.setNumberOfRequestBody(numberOfRequestBody);
        response.setNumberOfIncompleteRequestBody(numberOfIncompleteRequestBody);
        
        response.setResponseContents(responseContents);
        response.setNumberOfResponseBody(numberOfResponseBody);
        response.setNumberOfIncompleteResponseBody(numberOfIncompleteResponseBody);
        
        response.setReservationResponses(reservationResponses);
        response.setSummaryRateResponse(summaryRateResponse);
        
        return response;
    }
}
